package com.util.Algorithm.NeuralNetworks;

import com.entity.NeuralNetworks.NeuralNetworks;
import com.entity.NeuralNetworks.Neurons;

import java.math.BigInteger;
import java.util.Arrays;

/**
 * Created by wlc on 2018/5/23.
 */
public class BackPropagation implements LearningAlgorithm {
    @Override
    public void train(NeuralNetworks neuralNetworks,Double[][] trainSet,Double[] label) {
        for (int i = 0; i < trainSet.length; i++){
            //1 取样
            Double[] sample = trainSet[i];
            Double tag = label[i];
            //2 前向传播
            for (int j = 0; j < neuralNetworks.getInputNeuronId().size(); j++){
                BigInteger inputId = neuralNetworks.getInputNeuronId().get(j);
                Neurons inputNeurons = neuralNetworks.getNeuronCollection().get(inputId);
                inputNeurons.setInputValues(new BigInteger(String.valueOf(j)),sample[j]);
                inputNeurons.computeOutput();
                neuralNetworks.setNeuronCollection(inputId,inputNeurons);
            }
            neuralNetworks.computeOutValue();
            //3 反向传播
            Integer classifyNum = neuralNetworks.getOutputNeuronId().size();
            Double[] expectedOutput = new Double[classifyNum];
            Arrays.fill(expectedOutput,0d);
            expectedOutput[tag.intValue()] = 1d;
            for (int j = 0; j < classifyNum;j++){
                BigInteger outputId = neuralNetworks.getOutputNeuronId().get(j);
                Neurons outputNeurons = neuralNetworks.getNeuronCollection().get(outputId);
                outputNeurons.setTotalDeviation((expectedOutput[j]-outputNeurons.getOutputValue())*outputNeurons.getOutputValue()*(1d-outputNeurons.getOutputValue()));
                outputNeurons.computeDeviation();
                neuralNetworks.setNeuronCollection(outputId,outputNeurons);
            }
            neuralNetworks.computeDeviation();
            //4 更新
            neuralNetworks.update();
        }
    }

    @Override
    public void train(NeuralNetworks neuralNetworks,Double[][] trainSet){}
}
